#pragma once

#include <thread>
#include <vector>
#include <functional>
#include <libusb.h>
#include "hidbox/types.h"
#include "hidbox/hid_device_identifier.h"
#include "hidbox/hid_gadget_descriptor.h"

namespace hidbox {

/**
 * @brief 输入 HID 设备
 * 负责从物理 USB HID 设备读取数据
 */
class InputHIDDevice {
public:
    using InputCallback = std::function<void(u8* data, u32 length)>;

    explicit InputHIDDevice(HIDDeviceIdentifier identifier);
    virtual ~InputHIDDevice();

    /**
     * @brief 打开 USB 设备
     */
    void Open();

    /**
     * @brief 开始读取输入
     */
    void StartReadInput();

    /**
     * @brief 停止读取输入
     */
    void StopReadInput();

    /**
     * @brief 获取设备描述符
     * @return HIDGadgetDescriptor 引用
     */
    [[nodiscard]] const HIDGadgetDescriptor& GetDescriptor() const { return descriptor; }

    /**
     * @brief 设置输入回调函数
     * @param callback 回调函数
     */
    void SetInputCallback(InputCallback callback) { input_callback = std::move(callback); }

protected:
    const HIDDeviceIdentifier identifier;
    HIDGadgetDescriptor descriptor{};
    InputCallback input_callback;

    /**
     * @brief 匹配接口描述符（可被子类重写）
     * @param interface_desc 接口描述符
     * @return true 如果匹配
     */
    virtual bool MatchInterfaceDescriptor(const libusb_interface_descriptor* interface_desc);

    /**
     * @brief 初始化协议（可被子类重写）
     */
    virtual void InitProtocol() {}

    /**
     * @brief 处理输入数据（可被子类重写）
     * @param data 数据指针
     * @param length 数据长度
     */
    virtual void HandleInput(u8* data, u32 length);

private:
    u8 interface_num{};
    libusb_context* usb_ctx{};
    libusb_device_handle* usb_handle{};
    libusb_transfer* usb_transfer{};
    u16 input_ep_max_packet_size{};
    u8 input_endpoint{};
    u8 output_endpoint{};
    bool is_running{};
    std::thread thread;

    void OpenUSB(libusb_device* dev,
                 const libusb_device_descriptor* desc,
                 const libusb_interface_descriptor* interface_desc);

    void ReadCallback(libusb_transfer* transfer);

    static size_t ParseReportDescriptorSize(const libusb_interface_descriptor* interface_desc);
};

}  // namespace hidbox
